package com.yc.pre.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yc.pre.config.security.PreSignUserDetails;
import com.yc.pre.entity.dto.CaptchaDetail;
import com.yc.pre.entity.dto.PreLoginResponse;
import com.yc.pre.entity.order.PreSignUserOrderField;
import com.yc.pre.consts.SortOrderConsts;
import com.yc.pre.entity.PageResult;
import com.yc.pre.entity.PreUserJwtRes;
import com.yc.pre.entity.bean.PreSignUser;
import com.yc.pre.entity.dto.PreSignUserDto;
import com.yc.pre.entity.vo.*;
import com.yc.pre.mapper.primary.PreRolePermissionConfigMapper;
import com.yc.pre.mapper.primary.PreSignUserMapper;
import com.yc.pre.service.PreSignUserService;
import com.yc.pre.utils.JwtUtil;
import com.yc.pre.utils.MathUtils;
import com.yc.pre.utils.RedisUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName PreSignUserServiceImpl
 * @Description 试标库用户实现类
 * @Date 2021/02/08 15:06:00
 * @Created by ccc-j
 * @email ccc-ju@outlook.com
 */
@Service
public class PreSignUserServiceImpl implements PreSignUserService {

    @Resource
    private PreSignUserMapper preSignUserMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private PreRolePermissionConfigMapper preRolePermissionConfigMapper;

    @Override
    public PageResult<PreSignUserDto> getAllUser(PreSignUserVo preSignUserVo){
        PageHelper.startPage(preSignUserVo.getPage(), preSignUserVo.getNum());
        QueryWrapper<PreSignUser> queryWrapper = new QueryWrapper<>();
        if(preSignUserVo.getOrderField().equals(PreSignUserOrderField.DEFAULT)){
            queryWrapper.orderByDesc("id");
        }else if(preSignUserVo.getOrderField().equals(PreSignUserOrderField.SIGN_NUM)){
            queryWrapper.orderBy(true, preSignUserVo.getSortOrder().equals(SortOrderConsts.ASC) ? true : false, "sign_num");
        }else if(preSignUserVo.getOrderField().equals(PreSignUserOrderField.BAD_ERROR_RATE)){
            queryWrapper.orderBy(true, preSignUserVo.getSortOrder().equals(SortOrderConsts.ASC) ? true : false, "bad_error_rate");
        }else if(preSignUserVo.getOrderField().equals(PreSignUserOrderField.NOT_INCLUDE_ERROR_RATE)){
            queryWrapper.orderBy(true, preSignUserVo.getSortOrder().equals(SortOrderConsts.ASC) ? true : false, "not_include_error_rate");
        }
        // 排除管理员账号
        queryWrapper.lambda().ne(true, PreSignUser::getId, "1");
        List<PreSignUser> preSignUsers = preSignUserMapper.selectList(queryWrapper);
        List<PreSignUserDto> results = new ArrayList<>();
        if(ObjectUtils.isNotEmpty(preSignUsers) && preSignUsers.size() > 0){
            preSignUsers.forEach(x -> {
                PreSignUserDto user = PreSignUserDto.builder()
                        .id(x.getId())
                        .phone(x.getPhone())
                        .userName(x.getUserName())
                        .signNum(x.getSignNum())
                        .badErrorRate(MathUtils.caculateRate(x.getBadErrorNum(), x.getSignNum()))
                        .normalErrorRate(MathUtils.caculateRate(x.getNormalErrorNum(), x.getSignNum()))
                        .notIncludeErrorRate(MathUtils.caculateRate(x.getNotIncludeErrorNum(), x.getSignNum()))
                        .build();
                results.add(user);

            });
        }
        PageInfo<PreSignUserDto> pageInfo = new PageInfo<>(results);
        PageResult<PreSignUserDto> pageResult = PageResult.of(pageInfo, results);
        return pageResult;
    }

    /**
     * 登录方法
     * @param userLoginVo
     * @return
     */
    @Override
    public PreUserJwtRes login(UserLoginVo userLoginVo) {
        try{
            Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userLoginVo.getPhone(), userLoginVo.getPassword()));
            PreSignUserDetails preSignUserDetails = (PreSignUserDetails) authenticate.getPrincipal();
            // 生成token
            String token = JwtUtil.createJWT(String.valueOf(preSignUserDetails.getPreSignUser().getId()), preSignUserDetails.getPreSignUser().getUserName(), null);
            // 构建返回参数
            PreUserJwtRes jwtRes = PreUserJwtRes.builder()
                    .token(token)
                    .id(preSignUserDetails.getPreSignUser().getId())
                    .phone(preSignUserDetails.getPreSignUser().getPhone())
                    .name(preSignUserDetails.getPreSignUser().getUserName())
                    .roleName(preSignUserDetails.getPreSignUser().getPreRole().getRoleName())
                    .config(preRolePermissionConfigMapper.findConfig(preSignUserDetails.getPreSignUser().getPreRole().getId()))
                    .build();
            redisTemplate.opsForValue().set(RedisUtil.getLoginKey(), JSON.toJSONString(jwtRes), 1440, TimeUnit.MINUTES);
            return jwtRes;
        }catch (Exception e){
            String num  = (String) redisTemplate.opsForValue().get("COUNT_ERROR_" + userLoginVo.getPhone());
            // 出错了可能密码错误，这时需要计算错误
            if(ObjectUtils.isEmpty(num)){
                Integer count = 1;
                redisTemplate.opsForValue().set("COUNT_ERROR_" + userLoginVo.getPhone(), count.toString());
            }else{
                Integer count = Integer.parseInt(num) + 1;
                redisTemplate.opsForValue().set("COUNT_ERROR_" + userLoginVo.getPhone(), count.toString());
            }
            throw new BadCredentialsException("username or password error");
        }
    }

    @Override
    public void updatePassword(EditPasswordRequest request, Long userId) {

    }

    @Override
    public void resetPassword(Long id) {

    }

    @Override
    public void deleteUser(Long id) {

    }

    @Override
    public void addUser(AddUserRequest request) {

    }

    @Override
    public CaptchaDetail getCaptcha(String phone) {
        return null;
    }

    @Override
    public PreLoginResponse preLogin(String phone) {
        return null;
    }


}
